#ifndef _RISCV_H_
#define _RISCV_H_

#include "types.h"

// 页表项（PTE）的标志位
#define PTE_V (1L << 0) // 有效位[citation:10]
#define PTE_R (1L << 1) // 可读[citation:10]
#define PTE_W (1L << 2) // 可写[citation:10]
#define PTE_X (1L << 3) // 可执行[citation:10]
#define PTE_U (1L << 4) // 用户模式可访问[citation:10]
#define PTE_G (1L << 5)
// 其他可能的标志位，如PTE_G（全局）、PTE_A（访问位）、PTE_D（脏位）根据实际需要添加

// 页表项中物理页号(PPN)的移位和掩码（Sv39方案）
#define PTE_PPN_SHIFT 10
#define PTE_PPN_MASK ((1L << 44) - 1) // 假设PPN为44位

// 从PTE中提取物理地址(PA)
#define PTE2PA(pte) (((pte) >> PTE_PPN_SHIFT) << PAGE_SHIFT)
// 从物理地址(PA)生成PTE
#define PA2PTE(pa) (((pa) >> PAGE_SHIFT) << PTE_PPN_SHIFT)

// 控制状态寄存器（CSR）地址
#define SATP_SV39 (8L << 60) // Satp mode for Sv39[citation:10]
// 构造SATP寄存器值：MODE | ASID | PPN
#define MAKE_SATP(pagetable) (SATP_SV39 | (((uint64)(pagetable) >> PAGE_SHIFT)))

// 寄存器读写辅助函数（内联汇编）
static inline uint64
r_satp()
{
    uint64 x;
    asm volatile("csrr %0, satp" : "=r"(x));
    return x;
}

static inline void
w_satp(uint64 x)
{
    asm volatile("csrw satp, %0" :: "r"(x));
}

// TLB屏障指令，用于刷新TLB[citation:10]
static inline void
sfence_vma()
{
    asm volatile("sfence.vma zero, zero");
}

#endif // _RISCV_H_